﻿using System;

namespace PropertyExpression.ControllableQuery.Test
{
    public partial class Paging
    {
        public static Paging<TRows, TCount> New<TRows, TCount>(TRows rows, TCount count)
        {
            return new Paging<TRows, TCount>(rows, count);
        }

        public static QBuilder Rows(Action<QBuilder> mainQuery, Action<QBuilder> orderBy,
            Param<int> start, Param<int> finish)
        {
            return new QBuilder(@"
SELECT  *
FROM    (SELECT *,
                ROW_NUMBER() OVER (ORDER BY ", orderBy, @") AS RowNumber
         FROM   (", mainQuery, @"
                ) _
        ) _
WHERE   RowNumber BETWEEN ", start, @" AND ", finish, @"
ORDER BY RowNumber;");
        }

        public static QBuilder Count(Action<QBuilder> mainQuery)
        {
            return new QBuilder(@"
SELECT  COUNT(*) AS Value
FROM    (", mainQuery, @"
        ) _");
        }

        public static Action<QBuilder> Rows2(Action<QBuilder> mainQuery, Func<object, SubQuery> orderBy,
            Param<int> start, Param<int> finish)
        {
            return builder => builder.Razor(new {mainQuery, orderBy, start, finish}, @"
SELECT  *
FROM    (SELECT *,
                ROW_NUMBER() OVER (ORDER BY @orderBy(null)) AS RowNumber
         FROM   (@mainQuery
                ) _
        ) _
WHERE   RowNumber BETWEEN @start AND @finish
ORDER BY RowNumber;");
        }

        public static Action<QBuilder> Count2(Action<QBuilder> mainQuery)
        {
            return builder => builder.Append(@"
SELECT  COUNT(*) AS Value
FROM    (", mainQuery, @"
        ) _");
        }

        public static Paging<QBuilder, QBuilder> RowsAndCount2(Action<QBuilder> mainQuery,
            Action<QBuilder> orderBy, Param<int> start, Param<int> finish)
        {
            return New(Rows(mainQuery, orderBy, start, finish), Count(mainQuery));
        }

        public static Paging<QBuilder, QBuilder> RowsAndCount3(Action<QBuilder> mainQuery,
            Action<QBuilder> orderBy, Action<QBuilder> start, Action<QBuilder> finish)
        {
            return New(
                new QBuilder().Razor(new {mainQuery, orderBy, start, finish}, @"
SELECT  *
FROM    (SELECT *,
                ROW_NUMBER() OVER (ORDER BY @orderBy) AS RowNumber
         FROM   (@mainQuery
                ) _
        ) _
WHERE   RowNumber BETWEEN @start AND @finish
ORDER BY RowNumber;"),
                new QBuilder(@"
SELECT  COUNT(*) AS Value
FROM    (", mainQuery, @"
        ) _"));
        }

        public static QBuilder RowsAndCount(Action<QBuilder> mainQuery, Action<QBuilder> orderBy,
            Param<int> start, Param<int> finish)
        {
            return new QBuilder(@"
SELECT  *
FROM    (SELECT *,
                ROW_NUMBER() OVER (ORDER BY ", orderBy, @") AS RowNumber
         FROM   (", mainQuery, @"
                ) _
        ) _
WHERE   RowNumber BETWEEN ", start, @" AND ", finish, @"
ORDER BY RowNumber;

SELECT  COUNT(*) AS Value
FROM    (", mainQuery, @"
        ) _");
        }
    }

    public class Paging<TRows, TCount>
    {
        private readonly TRows rows;
        private readonly TCount count;

        public Paging(TRows rows, TCount count)
        {
            this.rows = rows;
            this.count = count;
        }

        public TRows Rows
        {
            get { return rows; }
        }

        public TCount Count
        {
            get { return count; }
        }
    }
}